package com.lqwu.manymanythumb.service.impl;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lqwu.manymanythumb.common.ErrorCode;
import com.lqwu.manymanythumb.constant.RedisLuaScriptConstant;
import com.lqwu.manymanythumb.constant.ThumbConstant;
import com.lqwu.manymanythumb.exception.BusinessException;
import com.lqwu.manymanythumb.exception.ThrowUtils;
import com.lqwu.manymanythumb.mapper.ThumbMapper;
import com.lqwu.manymanythumb.model.entry.Blog;
import com.lqwu.manymanythumb.model.entry.Thumb;
import com.lqwu.manymanythumb.model.entry.User;
import com.lqwu.manymanythumb.model.enums.LuaStatusEnum;
import com.lqwu.manymanythumb.service.BlogService;
import com.lqwu.manymanythumb.service.ThumbService;
import com.lqwu.manymanythumb.service.UserService;
import com.lqwu.manymanythumb.unitl.RedisKeyUtil;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.support.TransactionTemplate;

import java.util.Arrays;

/**
* @author 伍立权
* @description 针对表【thumb】的数据库操作Service实现
* @createDate 2025-05-18 23:46:31
*/
@Service("thumbService")
@RequiredArgsConstructor
public class ThumbServiceRedisImpl extends ServiceImpl<ThumbMapper, Thumb>
    implements ThumbService{
    @Resource
    private UserService userService;
    @Resource
    @Lazy
    private BlogService blogService;
    //编程式事务
    @Resource
    private TransactionTemplate transactionTemplate;
    @Resource
    private final RedisTemplate<String, Object> redisTemplate;

    /**
     * 点赞
     * @param blogId
     * @param request
     * @return
     */
    @Override
    public boolean doThumb(Long blogId, HttpServletRequest request) {
        if (blogId == null) {
            throw new RuntimeException("参数错误");
        }
        // 获取博客详情
        Blog blog = blogService.getById(blogId);
        // 获取当前用户
        User loginUser = userService.getLoginUser(request);
        // 获取时间片
        String timeSlice = getTimeSlice();
        // 获取 Redis Key
        String tempThumbKey = RedisKeyUtil.getTempThumbKey(timeSlice);
        String userThumbKey = RedisKeyUtil.getUserThumbKey(loginUser.getId());
        // 执行Lua脚本
        long result = redisTemplate.execute(
                RedisLuaScriptConstant.THUMB_SCRIPT,       // 注入的脚本Bean
                Arrays.asList(tempThumbKey, userThumbKey), // KEYS 数组
                loginUser.getId(),                         // ARGV[1]
                blogId                                     // ARGV[2]
        );
        if (LuaStatusEnum.FAIL.getValue() == result) {
            throw new RuntimeException("用户已点赞");
        }

        // 更新成功才执行
        return LuaStatusEnum.SUCCESS.getValue() == result;
    }

    /**
     * 取消点赞
     * @param blogId
     * @param request
     * @return
     */
    @Override
    public boolean cancelThumb(Long blogId, HttpServletRequest request) {
        // 获取博客详情
        Blog blog = blogService.getById(blogId);
        // 获取当前用户
        User loginUser = userService.getLoginUser(request);
        // 获取时间片
        String timeSlice = getTimeSlice();
        // 获取 Redis Key
        String tempThumbKey = RedisKeyUtil.getTempThumbKey(timeSlice);
        String userThumbKey = RedisKeyUtil.getUserThumbKey(loginUser.getId());
        // 执行Lua脚本
        long result = redisTemplate.execute(
                RedisLuaScriptConstant.UNTHUMB_SCRIPT,       // 注入的脚本Bean
                Arrays.asList(tempThumbKey, userThumbKey), // KEYS 数组
                loginUser.getId(),                         // ARGV[1]
                blogId                                     // ARGV[2]
        );
        if (LuaStatusEnum.FAIL.getValue() == result) {
            throw new RuntimeException("用户未点赞");
        }

        // 更新成功才执行
        return LuaStatusEnum.SUCCESS.getValue() == result;
    }

    /**
     * 获取时间片(以便定时任务)
     * @return
     */
    private String getTimeSlice() {
        DateTime nowDate = DateUtil.date();
        // 获取到当前时间前最近的整数秒，比如当前 11:20:23 ，获取到 11:20:20
        return DateUtil.format(nowDate, "HH:mm:") + (DateUtil.second(nowDate) / 10) * 10;
    }

    /**
     * 判断用户是否已经点赞（从 Redis 中）
     * @param blogId
     * @param userId
     * @return
     */
    @Override
    public boolean hasThumb(Long blogId, Long userId) {
        return redisTemplate.opsForHash().hasKey(ThumbConstant.USER_THUMB_KEY_PREFIX + blogId, userId.toString());
    }

}




